package com.h5ve.wxmp.handler;

import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.h5ve.base.constant.CommonConstants;
import com.h5ve.wxmp.constant.ConfigConstant;
import com.h5ve.wxmp.constant.WebSocketConstant;
import com.h5ve.wxmp.entity.WxReply;
import com.h5ve.wxmp.entity.WxMsg;
import com.h5ve.wxmp.entity.WxUser;
import com.h5ve.wxmp.mapper.WxUserMapper;
import com.h5ve.wxmp.service.WxReplyService;
import com.h5ve.wxmp.service.WxMsgService;
import lombok.AllArgsConstructor;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutNewsMessage;
import me.chanjar.weixin.mp.builder.outxml.*;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType;

/**
 * @author www.joolun.com
 */
@Component
@AllArgsConstructor
public class MsgHandler extends AbstractHandler {

    private final WxReplyService wxReplyService;
    private final WxUserMapper wxUserMapper;
    private final WxMsgService wxMsgService;
    @Override
    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
                                    Map<String, Object> context, WxMpService wxMpService,
                                    WxSessionManager sessionManager) {
        //组装回复消息
        if (!wxMessage.getMsgType().equals(XmlMsgType.EVENT)) {
            WxMpXmlOutMessage rs;
            //TODO 可以选择将消息保存到本地
            WxUser wxUser = wxUserMapper.selectOne(Wrappers.<WxUser>lambdaQuery()
                    .eq(WxUser::getOpenId,wxMessage.getFromUser()));
            if(WxConsts.KefuMsgType.TEXT.equals(wxMessage.getMsgType())){//1、先处理是否有文本关键字回复
                //先全匹配
                List<WxReply> listWxReply = wxReplyService.list(Wrappers
                        .<WxReply>query().lambda()
                        .eq(WxReply::getType, ConfigConstant.WX_AUTO_REPLY_TYPE_3)
                        .eq(WxReply::getRepMate, ConfigConstant.WX_REP_MATE_1)
                        .eq(WxReply::getReqKey, wxMessage.getContent()));
                if(listWxReply !=null && listWxReply.size()>0){
                    rs = this.getWxMpXmlOutMessage(wxMessage, listWxReply,wxUser,wxMsgService);
                    if(rs != null){
                        return  rs;
                    }
                }
                //再半匹配
                listWxReply = wxReplyService.list(Wrappers
                        .<WxReply>query().lambda()
                        .eq(WxReply::getType, ConfigConstant.WX_AUTO_REPLY_TYPE_3)
                        .eq(WxReply::getRepMate, ConfigConstant.WX_REP_MATE_2)
                        .like(WxReply::getReqKey, wxMessage.getContent()));
                if(listWxReply !=null && listWxReply.size()>0) {
                    rs = this.getWxMpXmlOutMessage(wxMessage, listWxReply, wxUser,wxMsgService);
                    if (rs != null) {
                        return rs;
                    }
                }
            }
            //2、再处理消息回复
            List<WxReply> listWxReply = wxReplyService.list(Wrappers
                    .<WxReply>query().lambda()
                    .eq(WxReply::getType, ConfigConstant.WX_AUTO_REPLY_TYPE_2)
                    .eq(WxReply::getReqType, wxMessage.getMsgType()));
            rs = this.getWxMpXmlOutMessage(wxMessage, listWxReply,wxUser,wxMsgService);
            return rs;
        }
        return null;

    }

    /**
     * 组装回复消息，并记录消息
     * @param wxMessage
     * @param listWxReply
     * @return
     */
    public static WxMpXmlOutMessage getWxMpXmlOutMessage(WxMpXmlMessage wxMessage, List<WxReply> listWxReply, WxUser wxUser,
                                                         WxMsgService wxMsgService){
        WxMpXmlOutMessage wxMpXmlOutMessage = null;
        //记录接收消息
        WxMsg wxMsg = new WxMsg();
        wxMsg.setWxUserId(wxUser.getId().toString());
        wxMsg.setNickName(wxUser.getNickName());
        wxMsg.setHeadimgUrl(wxUser.getHeadimgUrl());
        wxMsg.setType(ConfigConstant.WX_MSG_TYPE_1);
        wxMsg.setRepEvent(wxMessage.getEvent());
        wxMsg.setRepType(wxMessage.getMsgType());
        wxMsg.setRepMediaId(wxMessage.getMediaId());
        if(WxConsts.XmlMsgType.TEXT.equals(wxMessage.getMsgType())){
            wxMsg.setRepContent(wxMessage.getContent());
        }
        if(WxConsts.XmlMsgType.VOICE.equals(wxMessage.getMsgType())){
            wxMsg.setRepName(wxMessage.getMediaId() + "." + wxMessage.getFormat());
            wxMsg.setRepContent(wxMessage.getRecognition());
        }
        if(WxConsts.XmlMsgType.IMAGE.equals(wxMessage.getMsgType())){
            wxMsg.setRepUrl(wxMessage.getPicUrl());
        }
        if(WxConsts.XmlMsgType.LINK.equals(wxMessage.getMsgType())){
            wxMsg.setRepName(wxMessage.getTitle());
            wxMsg.setRepDesc(wxMessage.getDescription());
            wxMsg.setRepUrl(wxMessage.getUrl());
        }
        if(WxConsts.MediaFileType.FILE.equals(wxMessage.getMsgType())){
            wxMsg.setRepName(wxMessage.getTitle());
            wxMsg.setRepDesc(wxMessage.getDescription());
        }
        if(WxConsts.XmlMsgType.VIDEO.equals(wxMessage.getMsgType())){
            wxMsg.setRepThumbMediaId(wxMessage.getThumbMediaId());
        }
        if(WxConsts.XmlMsgType.LOCATION.equals(wxMessage.getMsgType())){
            wxMsg.setRepLocationX(wxMessage.getLocationX());
            wxMsg.setRepLocationY(wxMessage.getLocationY());
            wxMsg.setRepScale(wxMessage.getScale());
            wxMsg.setRepContent(wxMessage.getLabel());
        }
        wxMsg.setReadFlag(CommonConstants.NO);
        wxMsgService.save(wxMsg);
        //推送websocket
        String destination = WebSocketConstant.USER_DESTINATION_PREFIX + WebSocketConstant.WX_MSG + wxMsg.getWxUserId();
        if(listWxReply !=null && listWxReply.size()>0){
            WxReply wxReply = listWxReply.get(0);
            //记录回复消息
            wxMsg = new WxMsg();
            wxMsg.setWxUserId(wxUser.getId().toString());
            wxMsg.setNickName(wxUser.getNickName());
            wxMsg.setHeadimgUrl(wxUser.getHeadimgUrl());
            wxMsg.setType(ConfigConstant.WX_MSG_TYPE_2);
            wxMsg.setRepType(wxReply.getRepType());

            if(WxConsts.KefuMsgType.TEXT.equals(wxReply.getRepType())){//文本
                wxMsg.setRepContent(wxReply.getRepContent());
                wxMpXmlOutMessage = new TextBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).content(wxReply.getRepContent()).build();
            }
            if(WxConsts.KefuMsgType.IMAGE.equals(wxReply.getRepType())){//图片
                wxMsg.setRepName(wxReply.getRepName());
                wxMsg.setRepUrl(wxReply.getRepUrl());
                wxMsg.setRepMediaId(wxReply.getRepMediaId());
                wxMpXmlOutMessage = new ImageBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).mediaId(wxReply.getRepMediaId()).build();
            }
            if(WxConsts.KefuMsgType.VOICE.equals(wxReply.getRepType())){
                wxMsg.setRepName(wxReply.getRepName());
                wxMsg.setRepUrl(wxReply.getRepUrl());
                wxMsg.setRepMediaId(wxReply.getRepMediaId());
                wxMpXmlOutMessage = new VoiceBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).mediaId(wxReply.getRepMediaId()).build();
            }
            if(WxConsts.KefuMsgType.VIDEO.equals(wxReply.getRepType())){
                wxMsg.setRepName(wxReply.getRepName());
                wxMsg.setRepDesc(wxReply.getRepDesc());
                wxMsg.setRepUrl(wxReply.getRepUrl());
                wxMsg.setRepMediaId(wxReply.getRepMediaId());
                wxMpXmlOutMessage = new VideoBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).mediaId(wxReply.getRepMediaId())
                        .title(wxReply.getRepName()).description(wxReply.getRepDesc()).build();
            }
            if(WxConsts.KefuMsgType.MUSIC.equals(wxReply.getRepType())){
                wxMsg.setRepName(wxReply.getRepName());
                wxMsg.setRepDesc(wxReply.getRepDesc());
                wxMsg.setRepUrl(wxReply.getRepUrl());
                wxMsg.setRepHqUrl(wxReply.getRepHqUrl());
                wxMsg.setRepThumbMediaId(wxReply.getRepThumbMediaId());
                wxMsg.setRepThumbUrl(wxReply.getRepThumbUrl());
                wxMpXmlOutMessage = new MusicBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
                        .thumbMediaId(wxReply.getRepThumbMediaId())
                        .title(wxReply.getRepName()).description(wxReply.getRepDesc())
                        .musicUrl(wxReply.getRepUrl()).hqMusicUrl(wxReply.getRepHqUrl()).build();
            }
            if(WxConsts.KefuMsgType.NEWS.equals(wxReply.getRepType())){
                List<WxMpXmlOutNewsMessage.Item> list = new ArrayList<>();
                List<JSONObject> listJSONObject = wxReply.getContent().getJSONArray("articles").toList(JSONObject.class);
                WxMpXmlOutNewsMessage.Item t;
                for(JSONObject jSONObject : listJSONObject){
                    t = new WxMpXmlOutNewsMessage.Item();
                    t.setTitle(jSONObject.getStr("title"));
                    t.setDescription(jSONObject.getStr("digest"));
                    t.setPicUrl(jSONObject.getStr("thumbUrl"));
                    t.setUrl(jSONObject.getStr("url"));
                    list.add(t);
                }
                wxMsg.setRepName(wxReply.getRepName());
                wxMsg.setRepDesc(wxReply.getRepDesc());
                wxMsg.setRepUrl(wxReply.getRepUrl());
                wxMsg.setRepMediaId(wxReply.getRepMediaId());
                wxMsg.setContent(wxReply.getContent());
                wxMpXmlOutMessage = new NewsBuilder().fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()).articles(list).build();
            }
            wxMsgService.save(wxMsg);
        }
        return wxMpXmlOutMessage;
    }
}
